package com.googlecode.klenwell.playndev.core.event;

import java.util.HashMap;
import java.util.LinkedList;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import playn.core.Pointer.Event;

public class EventApi {

    public static LinkedList<GameEvent> eventQueue = Lists.newLinkedList();
    public static HashMap<EventType, LinkedList<EventBinding>> WATCHING = Maps.newHashMap();

    public static void enqueue(GameEvent gameEvent) {
        eventQueue.add(gameEvent);        
    }

    public static GameEvent normalizeEvent(EventType type, Event event) {
        GameEvent gameEvent = null;
        
        if ( type == EventType.POINTERSTART ) {
            gameEvent = new GameEvent(EventType.POINTERSTART, event);
        } else if ( type == EventType.POINTEREND ) {
            gameEvent = new GameEvent(EventType.POINTEREND, event);
        } else if ( type == EventType.POINTERDRAG ) {
            gameEvent = new GameEvent(EventType.POINTERDRAG, event);
        } else {
            throw new IllegalStateException("invalid event type");
        }
        
        return gameEvent;
    }

    public static void bind(EventType eventType, EventListener target,
            String callbackKey) {
        EventBinding binding = new EventBinding(eventType, target, callbackKey);
        
        LinkedList<EventBinding> bindings = WATCHING.get(eventType);
        if ( bindings == null ) {
            bindings = new LinkedList<EventBinding>();
            bindings.add(binding);
            WATCHING.put(eventType, bindings);
        }
        else {
            bindings.add(binding);
        }        
    }

    public static void processQueue() {
        while ( ! eventQueue.isEmpty() ) {
            GameEvent event = eventQueue.removeLast();
            processEvent(event);
        }        
    }

    private static void processEvent(GameEvent event) {
        LinkedList<EventBinding> bindings = WATCHING.get(event.type);
        
        if ( bindings == null ) {
            return;
        }
        
        for (EventBinding binding : bindings) {
            processBinding(event, binding);
        }
        
    }

    private static void processBinding(GameEvent event, EventBinding binding) {
        event.addBinding(binding);
        binding.target.processBoundEvent(event);
    }

}
